﻿using System;
using ALDIOrganizer.Properties;

namespace ALDIOrganizer
{
    public static class PositionExtensionMethods
    {
        public static Position FromInt(this Position p, Int64 integer)
        {
            var result = Position.None;
            try
            {
                result = (Position)Enum.ToObject(typeof(Position), integer);
            }
            catch { }

            // if there is an pException, _role.None (Initial Value) is returned
            return result;
        }

        public static Position GetAsOnProd(this Position p)
        {
            return (p & Position.Trainee) == 0 ?
            p :
            ((long)p - (long)Position.Trainee).To<Position>();
        }

        public static Position GetAsOffProd(this Position p)
        {
            return (p & Position.Trainee) != 0 ?
            p :
            ((long)p + (long)Position.Trainee).To<Position>();
        }

        public static bool IsOffProd(this Position p)
        {
            return (p & Position.Trainee) > 0;
        }

        public static string ToShortString(this Position p)
        {
            var wasOffProd = p.IsOffProd();
            p = p.GetAsOnProd();
            string result;
            switch (p)
            {
                case Position.None:
                    {
                        result = Resources.POSITION_SHORT_None;
                        break;
                    }
                case Position.External:
                    {
                        result = Resources.POSITION_SHORT_External;
                        break;
                    }

                case Position.Trainee:
                    {
                        result = Resources.POSITION_SHORT_OffProd; // "off productivity"
                        break;
                    }
                case Position.StoreAssistant:
                    {
                        result = Resources.POSITION_SHORT_StoreAssistant;
                        break;
                    }
                case Position.StoreDeputy:
                    {
                        result = Resources.POSITION_SHORT_StoreDeputy;
                        break;
                    }
                case Position.AssistantManager:
                    {
                        result = Resources.POSITION_SHORT_AssistantManager;
                        break;
                    }
                case Position.StoreManager:
                    {
                        result = Resources.POSITION_SHORT_StoreManager;
                        break;
                    }
                default: return String.Empty;
            }
            return result + (wasOffProd ? Resources.POSITION_SHORT_OffProd : String.Empty);
        }

        public static string ToLongString(this Position p)
        {
            if (p == Position.Trainee)
            {
                return Resources.POSITION_Trainee;
            }
            if (p == PositionExtensionMethods.Anyone)
            {
                return Resources.POSITION_Anyone;
            }
            if (p == PositionExtensionMethods.Assistant)
            {
                return Resources.POSITION_Assistant;
            }
            if (p == PositionExtensionMethods.Manager)
            {
                return Resources.POSITION_Manager;
            }
            if (p == PositionExtensionMethods.StoreRunner)
            {
                return Resources.POSITION_StoreRunner;
            }
            if ((p & Position.Trainee) != 0)
            {
                // we take the off productivity (trainee) flag off
                var i2 = (Int64)p - (Int64)Position.Trainee;
                var p2 = i2.To<Position>();
                // and we return the "normal" _role Name, PLUS annotation
                return p2.ToLongString() + Resources.POSITION_OffProd;
            }
            // else...
            switch (p)
            {
                case Position.External: return Resources.POSITION_External;

                case Position.StoreAssistant: return Resources.POSITION_StoreAssistant;

                case Position.StoreDeputy: return Resources.POSITION_StoreDeputy;

                case Position.AssistantManager: return Resources.POSITION_AssistantManager;

                case Position.StoreManager: return Resources.POSITION_StoreManager;

                default: return String.Empty;

            }
        }

        public static string Explanation(this Position pPosition)
        {
            #region non-standard (aggregate) values
            if (pPosition == PositionExtensionMethods.StoreRunner)
            {
                return Resources.POSITION_DEFINED_StoreRunner;
            }
            if (pPosition == PositionExtensionMethods.Manager)
            {
                return Resources.POSITION_DEFINED_Manager;
            }
            if (pPosition == PositionExtensionMethods.Anyone)
            {
                return Resources.POSITION_DEFINED_Anyone;
            }
            if (pPosition == PositionExtensionMethods.Assistant)
            {
                return Resources.POSITION_DEFINED_Assistant;
            }
            #endregion

            switch (pPosition)
            {
                case Position.External:
                    {
                        return Resources.POSITION_DEFINED_External;
                    }
                case Position.Trainee:
                    {
                        return Resources.POSITION_DEFINED_Trainee;
                    }
                default:
                    {
                        return Resources.POSITION_DEFINED_AnyWildcard.Replace(
                            "#",
                            pPosition.ToLongString());
                    }
            }
        }


        public static bool IsStoreRunner(this Position p)
        {
            return ((p & StoreRunner) != 0); 
        }

        public static bool Matches(
            this Position pCandidate,
            Position pShiftsPosition)
        {
            // trainee shifts are for trainees only. and vice versa.
            if (pCandidate.IsOffProd() ^ pShiftsPosition.IsOffProd())
            {
                return false;
            }

            return (pCandidate & pShiftsPosition) != 0;
        }

        // utilizing flags to create "general purpose" concepts which cater several positions at once
        public static readonly Position Manager = Position.StoreManager | Position.AssistantManager;
        public static readonly Position StoreRunner = Position.StoreManager | Position.AssistantManager | Position.StoreDeputy;
        public static readonly Position Anyone =
            Position.StoreManager |
            Position.AssistantManager |
            Position.StoreDeputy |
            Position.StoreAssistant;
        public static readonly Position Assistant = Position.StoreDeputy | Position.StoreAssistant;

        public static Position[] SortOrder()
        {
            return new[]
            {
                StoreRunner,
                Position.StoreManager,
                Manager,
                Position.AssistantManager,
                Position.StoreDeputy,
                Anyone,
                Assistant,
                Position.StoreAssistant,
                Position.Trainee,
                Position.External,
                Position.None
            };
        }

        public static int CompareWith(this Position pPosition, Position pOther)
        {
            var myIndex = Array.IndexOf(SortOrder(), pPosition);
            var otherIndex = Array.IndexOf(SortOrder(), pOther);
            return myIndex.CompareTo(otherIndex);
        }
    }
}
